require 'rvg/rvg'
include Magick

class Saucy

  def Saucy.render_text text, attrs, font_store

    font_size = attrs[:size] || 10
    font = attrs[:font] || 'arial.ttf'
    b_color = attrs[:background] || "transparent"
    color = attrs[:color] || 'black'
    if attrs[:outline]
      stroke_color = attrs[:outline][:color] || 'black'
      stroke_width = attrs[:outline][:width] || 0
      stroke_inside = attrs[:outline][:inside] || 0
    else
      stroke_width = 0
      stroke_inside = 0
      stroke_color = 'black'
    end

    #rvg = RVG.new(5000,5000) do |canvas|
    rvg = RVG.new(font_size*text.length*2 + stroke_width*2, font_size*2+ stroke_width*2) do |canvas|
      if(b_color != 'transparent')
       canvas.background_fill = b_color
      end

      if FileTest.exists?(File.join(font_store, font))
        font_file = File.join(font_store, font)
      else
        font_file = File.join(font_store, '/arial.ttf')
      end
      sw = stroke_width

      if sw == 0
        canvas.text(0+sw,font_size+sw, text).styles(:font => '"' + font_file + '"', :font_size=>font_size, :fill=>color)
	    else
		    canvas.text(0+sw,font_size+sw, text).styles(:font => '"' + font_file + '"', :font_size=>font_size, :fill=>color, :stroke => stroke_color, :stroke_width => stroke_width)
  	  end

      if stroke_inside > 0
         canvas.text(0+sw,font_size+sw, text).styles(:font => '"' + font_file +'"', :font_size => font_size, :fill=> color, :stroke_width => stroke_inside, :stroke => color )
      end
    end
    img = rvg.draw

    #img.trim
  end

  def Saucy.render_gradient attrs, texture_store
    direction  = attrs[:direction] || 'x'
    bg_start_color = attrs[:background][:color] || 'white'
    bg_end_color = attrs[:background][:color_end] || attrs[:background][:color]
    texture_start_color = attrs[:texture][:color] || attrs[:background][:color]
    texture_end_color = attrs[:texture][:color_end] || attrs[:texture][:color]
    texture_opacity =  ((attrs[:texture][:opacity] || 1.0).to_f * 255).to_i
    opacity_start = ((attrs[:background][:opacity] || 1.0).to_f * 255).to_i
    opacity_end = ((attrs[:background][:opacity_end] || attrs[:background][:opacity]).to_f * 255).to_i

    size = attrs[:size] || 100
    texture_tile  = attrs[:texture][:tile]

    texture_img = Image.read(texture_store + texture_tile).first if texture_tile

    if(direction == 'x')
      width = size
      height = ( texture_tile ? texture_img.rows : 10 )
      bg = GradientFill.new(0, 0, 0, width, bg_start_color, bg_end_color)
      texture = GradientFill.new(0, 0, 0, width, texture_start_color, texture_end_color)
    elsif(direction == 'y')
      height = size
      width = texture_tile ? texture_img.columns : 10
      bg = GradientFill.new(0, 0, height, 0, bg_start_color, bg_end_color)
      texture = GradientFill.new(0, 0, height, 0, texture_start_color, texture_end_color)
    end

    img_bg = Image.new(width, height, bg)
    img_texture = Image.new(width, height, texture)

    unless texture_tile == nil
      mask  = ImageList.new
      mask_fill =  TextureFill.new(texture_img)
      mask.new_image(width, height)

      gc = Draw.new
      gc.pattern('mask', 0, 0, texture_img.columns, texture_img.rows) { gc.composite(0,0,texture_img.columns,texture_img.rows,texture_img) }
      gc.fill('mask')
      gc.rectangle(0,0,width,height)
      gc.draw(mask)

      mask = mask.negate
      mask.matte=false

      opacity_color = "rgb(#{texture_opacity},#{texture_opacity},#{texture_opacity})"
      mask_trans = Image.new(width, height) {self.background_color = opacity_color}
      mask_trans.matte=true
      mask_trans.composite!(mask,0,0, CopyOpacityCompositeOp)
      mask_trans2 = Image.new(width, height) {self.background_color = '#000'}
      mask_trans2.composite!(mask_trans,0,0, OverCompositeOp)

      mask_trans2.matte=false

      img_texture.matte=true
      img_texture.composite!(mask_trans2,0,0, CopyOpacityCompositeOp)
      img_texture.matte=true

      img_bg.composite!(img_texture,0,0, OverCompositeOp)

    end

    if (opacity_start && opacity_end)
      os = (255*opacity_start.to_f).floor
      oe = (255*opacity_end.to_f).floor

      if direction == 'x'
        h,w=0,width
      else
        h,w=height,0
      end

      opacity_gradient = GradientFill.new(0, 0, h, w,"rgb(#{os},#{os},#{os})", "rgb(#{oe},#{oe},#{oe})")

      img_bg.matte=true
      opacity_mask = Image.new(width, height, opacity_gradient)
      opacity_mask.matte=false
      img_bg.composite!(opacity_mask, 0,0, CopyOpacityCompositeOp)

    end

    img_bg
  end

  def Saucy.render_shadow input, attrs

#    matte = (attrs['psm'] || 'transparent')
    shadow_color = attrs[:color] || '#888'
    shadow_opacity = 255 - ((attrs[:opacity] || 0.7) * 255).to_i
    shadow_top = attrs[:top] || 3
    shadow_left = attrs[:left] || 3
    blur_radius = attrs[:radius] || 2.0

    w=input.columns+ blur_radius*4+shadow_left.abs*2
    h=input.rows+ blur_radius*4+shadow_top.abs*2

    input.matte = true

    opacity_color = "rgb(#{shadow_opacity},#{shadow_opacity},#{shadow_opacity})"
    input_colorized= input.copy.colorize(1.0, 1.0, 1.0, opacity_color)

    shadow_mask =  Image.new(w,h ){self.background_color = '#fff'}

    zero=[shadow_left.abs+blur_radius,shadow_top.abs+blur_radius]

    shadow_mask.composite!(input_colorized, blur_radius, blur_radius, OverCompositeOp)

    shadow_mask.matte=true
    shadow_mask = shadow_mask.blur_image(blur_radius,blur_radius)

    output = Image.new(w,h){self.background_color = shadow_color}
    inverse_shadow_mask = shadow_mask.negate
    inverse_shadow_mask.matte = false

    output.matte = true
    output.composite!(inverse_shadow_mask, zero[0]+shadow_left,zero[1]+shadow_top, CopyOpacityCompositeOp)

    output.composite!(input, zero[0]+blur_radius,zero[1]+blur_radius, OverCompositeOp)
    output.trim
  end

=begin
  def curve_render attrs
    r = attrs['r'].to_i
    sw = attrs['sw'].to_i
    oc = attrs['oc'].gsub('H','#')
    sc = attrs['sc'].gsub('H','#')
    ic = attrs['ic'].gsub('H','#')
    w = attrs['w'].to_i
    h = attrs['h'].to_i
    b = attrs['b']

    tAdd = (b[0..0] == '0') ? 1 : 0
    rAdd = (b[1..1] == '0') ? 1 : 0
    bAdd = (b[2..2] == '0') ? 1 : 0
    lAdd = (b[3..3] == '0') ? 1 : 0

    img = ImageList.new
    img.new_image(w,h) { self.background_color = 'transparent'}
    gc  = Draw.new

    if(ic != 'transparent')
      gc.fill_opacity(255)
      gc.fill(ic)
    else
      gc.fill_opacity(0)
    end

    if oc != 'transparent'
      gc.stroke(oc)
      gc.stroke_width(r-1)
      a = 1
      rad = r *3/2
      left = -r/2 + 0  - r*(lAdd)
      top = -r/2 + 0 - r*(tAdd)
      width = w+r/2 - a + r*(rAdd)
      height = h+r/2 - a + r*(bAdd)
#      gc.roundrectangle(-r/2 + a,-r/2 + a,w+r/2 - a,h+r/2 - a, r*3/2,r*3/2)
      gc.roundrectangle(left, top, width, height, rad,rad )
    end

    if sc != 'transparent'
      gc.stroke(sc)
      gc.stroke_width(sw)
      # Draw rounded rectangle
      a = 1

      rad = r-sw/2
      left = sw/2+0 - r*(lAdd)
      top = sw/2+0 - r*(tAdd)
      width = w-sw/2-a + r*(rAdd)
      height = h-sw/2-a + r*(bAdd)

      gc.roundrectangle(left, top, width, height, rad,rad )
 #gc.roundrectangle(bw/2+a,bw/2+a, w-bw/2-a,h-bw/2-a,r-bw/2,r-bw/2)
    end

    gc.draw(img)
    img
  end

  def liquid_curve_render attrs
    root2 = 1.4142135623730950488016887242097
    r = attrs['r'].to_i
    bw = attrs['bw'].to_i
    ir = r - bw
    oc = attrs['oc'].gsub('H','#').gsub('H','#')
    bc = attrs['bc'].gsub('H','#').gsub('H','#')
    ic = attrs['ic'].gsub('H','#').gsub('H','#')

    img = ImageList.new
    img.new_image(r, r) { self.background_color = 'transparent'}
    gc  = Draw.new

    #BL
    big = r * root2

    gc.fill_opacity(0)
    if oc != 'transparent'
      gc.stroke(oc).stroke_width((big-ir)*2)
      gc.arc(-big,-big,big,big,0,270)
    end

    inner2 = bw*0.5 + ir - 0.5

    if bc != 'transparent'
      if(ic != 'transparent')
        gc.fill_opacity(255)
        gc.fill(ic)
      end
      gc.stroke(bc).stroke_width(bw)
      gc.arc(-inner2,-inner2,inner2,inner2,0,270)
    end

    gc.draw(img)
    img.write(img_prefix + 'br'  + img_postfix)

    border_img = img.crop(0,0,1,r)

    img.write(img_prefix + 'br'  + img_postfix)
    img.rotate(90).write(img_prefix + 'bl'  + img_postfix)
    img.rotate(180).write(img_prefix + 'tl'  + img_postfix)
    img.rotate(270).write(img_prefix + 'tr'  + img_postfix)

    border_img.write(img_prefix + 'b'  + img_postfix)
    border_img.rotate(90).write(img_prefix + 'l'  + img_postfix)
    border_img.rotate(180).write(img_prefix + 't'  + img_postfix)
    border_img.rotate(270).write(img_prefix + 'r'  + img_postfix)

  end

  def rotate_render input, attrs
    angle=attrs['pr'].to_i
    input.matte = true
    input.rotate!(angle)
    input
  end

  def guassian_blur_render input, attrs
    blur_radius = (attrs['pg'] || '10').to_f
    w=input.columns#+ blur_radius*2
    h=input.rows#+ blur_radius*2
    output = Image.new(w,h) {self.background_color = 'transparent'}

    blur = input.blur_image(blur_radius/2,blur_radius/2)
    output.composite!(blur, 0,0, OverCompositeOp)
    output
  end

  def post_render input, attrs
    input = rotate_render input, attrs if attrs['pr']
    input = shadow_render input, attrs if attrs['ps']
    input = guassian_blur_render input, attrs if attrs['pg']

    # background render
    if (attrs['pb'] != 'transparent')
      bg = Image.new(input.columns, input.rows) {self.background_color = attrs['pb'].gsub('H','#')}
      input = bg.composite(input,0,0,OverCompositeOp)
    end
    input
  end

    #if :use_cache => false, saucy will render the image every time, useful for debugging saucy the lib
  def initialize attrs
    @use_cache=attrs[:use_cache] || true
    @image_store = attrs[:image_store]
    @font_store = attrs[:font_store]
    @texture_store = attrs[:texture_store]
  end
=end

=begin
  def render filename

    render_type = filename.slice(0..0)
    name = filename.slice(0...filename.length-4) #.gsub(/HX/,'#')
    output_path = @image_store + filename

    if !@use_cache || !(FileTest.exists? output_path)
      img_attrs = name.slice(2...name.length) #cut off the first

      attrs  = {}
      img_attrs.split('~').each do |param|
        k=param.split('-')
        attrs[k[0]] = CGI.unescape(k[1])
      end

      case render_type
        when 't'
          pre = ttf_render(attrs)
        when 'c'
          pre = curve_render(attrs)
        when 'g'
          pre = gradient_render(attrs)
        else
          raise('no such type')
      end


    end
    output_path
  end
=end

end
